// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

using Furion.Schedule;
using Furion.TimeCrontab;
using Neto.Logging.AutoDeleted.Options;
using System.Globalization;

namespace Neto.Logging.AutoDeleted;

/// <summary>
///     日志自动删除任务
/// </summary>
[JobDetail("job_AutoDeletedJob", "日志自动删除任务")]
//每天0点运行一次
[Cron("0 0 0 * * ?", CronStringFormat.WithSeconds, TriggerId = "trigger_AutoDeletedJob")]
public class AutoDeletedJob : IJob
{
    public Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
    {
        var logFloder = Path.Combine(
            App.HostEnvironment.ContentRootPath,
            "logs"
        ).ToOsDirectory();

        var options = AppX.GetConfig<FurionLoggingAutoDeletedOptions>();

        DeleteFloder(options, logFloder);

        return Task.CompletedTask;
    }

    /// <summary>
    ///     删除日志
    ///     注意：不影响Serilog的删除日志逻辑
    /// </summary>
    /// <param name="options"></param>
    /// <param name="logFloder"></param>
    private void DeleteFloder(FurionLoggingAutoDeletedOptions options, string logFloder)
    {
        try
        {
            if (options.IsEnable == false) return;

            //如果保留最大日志文件夹数小于等于0，则不删除
            if (options.RetainedFloderCountLimit.HasValue == false ||
                options.RetainedFloderCountLimit.Value <= 0) return;


            //获取程序更目录，要分别注意是web还是host
            //var directory = GetLogFullFileFloderPath(serilogConfigOptions, logFloderName);
            //var directory = Path.GetDirectoryName(logPath);

            // 新增目录存在性检查
            Console.WriteLine($"Checking directory: {logFloder}");
            if (!Directory.Exists(logFloder))
            {
                Console.WriteLine($"Directory not exist: {logFloder}");
                return;
            }

            // 获取文件保留天数
            var fileRetentionDays = Math.Max(1, options?.RetainedFileCountLimit ?? 10);
            var fileCutoffDate = DateTime.Today.AddDays(-fileRetentionDays);
            // 保留文件夹天数
            var floderRetentionDays = Math.Max(1, options?.RetainedFloderCountLimit ?? 7);
            var floderCutoffDate = DateTime.Today.AddDays(-floderRetentionDays);


            // 处理日期格式文件夹
            var directories = Directory.GetDirectories(logFloder)
                .Select(d => new { Path = d, Name = Path.GetFileName(d) })
                .Where(d => TryParseDateFromString(d.Name, out var date))
                .Select(d => new
                {
                    d.Path,
                    Date = DateTime.ParseExact(d.Name, ["yyyy-MM-dd", "yyyyMMdd"], null, DateTimeStyles.None)
                });

            // 处理日期格式文件（适配多种命名规则）
            var files = Directory.GetFiles(logFloder, "*.*") // 获取所有带扩展名的文件
                .Where(f =>
                {
                    var extension = Path.GetExtension(f).ToLower();
                    return extension is ".txt" or ".log"; // 仅选择 .txt 和 .log 文件
                })
                .Select(f => new
                {
                    Path = f,
                    FileName = Path.GetFileNameWithoutExtension(f),
                    Parts = Path.GetFileNameWithoutExtension(f).Split('_', '-') // 同时支持下划线和短横线分隔符
                })
                .Where(f => f.Parts.Length >= 2)
                .Select(f => new
                {
                    f.Path,
                    DateString = f.Parts[^1], // 取最后一个元素作为日期部分
                    f.Parts
                })
                .Where(f => TryParseDateFromString(f.DateString, out _))
                .Select(f => new
                {
                    f.Path,
                    Date = DateTime.ParseExact(
                        f.DateString,
                        ["yyyyMMdd", "yyyy-MM-dd", "yyyy_MM_dd"],
                        CultureInfo.InvariantCulture
                    )
                });

            // 合并需要删除的项目
            var itemsToDelete = directories
                .Select(d => new { d.Path, IsDirectory = true, d.Date })
                .Concat(files.Select(f => new { f.Path, IsDirectory = false, f.Date }))
                .Where(item =>
                    (item.IsDirectory && item.Date < floderCutoffDate) ||
                    (!item.IsDirectory && item.Date < fileCutoffDate)
                )
                .OrderBy(item => item.Date)
                .ToList();

            // 执行删除
            foreach (var item in itemsToDelete)
                try
                {
                    if (item.IsDirectory)
                        Directory.Delete(item.Path, true); // 递归删除文件夹
                    else
                        File.Delete(item.Path);

                    Console.WriteLine($"Deleted: {item.Path}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error deleting {item.Path}: {ex.Message}");
                    // 可记录到日志系统
                }
        }
        catch (Exception e)
        {
            Console.WriteLine($"DeleteFloder : {e.Message}");
            //throw;
        }
    }

    /// <summary>
    ///     判断是否是日期格式
    /// </summary>
    /// <param name="input"></param>
    /// <param name="date"></param>
    /// <returns></returns>
    private bool TryParseDateFromString(string input, out DateTime date)
    {
        // 支持 yyyy-MM-dd 和 yyyyMMdd 两种格式
        if (DateTime.TryParseExact(input, "yyyy-MM-dd", null, DateTimeStyles.None, out date))
            return true;

        return DateTime.TryParseExact(input, "yyyyMMdd", null, DateTimeStyles.None, out date);
    }
}